Jerry's Log

Circuit Breaker

contents

"회복력 있는(Resilient)" 시스템을 구축하기 위해 가장 중요한 패턴 중 하나인 서킷 브레이커(Circuit Breaker, 회로 차단기) 패턴에 대해 알아보겠습니다.

이 패턴이 없다면, 단 하나의 마이크로서비스 장애가 전체 아키텍처를 무너뜨릴 수 있습니다(도미노 효과).

다음은 서킷 브레이커 패턴의 핵심 개념, 내부 작동 원리, 그리고 Spring Boot에서의 구현 방법에 대한 상세 분석입니다.


1. 핵심 개념: "전기 퓨즈 (The Electrical Fuse)"

여러분의 집을 상상해 보세요. 만약 전자레인지가 합선되어 과도한 전류가 흐른다면 어떻게 될까요?

마이크로서비스 세계에서는:

Service AService B 를 호출했는데, Service B 가 죽었거나 매우 느리다고 가정해 봅시다.


2. 내부 상태 머신 (Internal State Machine)

서킷 브레이커는 세 가지 주요 상태를 가진 유한 상태 기계(Finite State Machine) 입니다.

A. CLOSED (닫힘 - 정상 상태)

B. OPEN (열림 - 장애 상태)

C. HALF-OPEN (반열림 - 테스트 상태)


3. Spring Boot에서 구현하기 (Resilience4j)

과거에는 Netflix Hystrix(현재 개발 중단됨)를 썼지만, 오늘날의 업계 표준은 Resilience4j입니다.

1단계: 의존성 추가


    org.springframework.cloud
    spring-cloud-starter-circuitbreaker-resilience4j


    org.springframework.boot
    spring-boot-starter-aop

2단계: 설정 (application.yml)

여기서 민감도를 설정합니다.

resilience4j:
  circuitbreaker:
    instances:
      paymentService: # 브레이커 이름
        registerHealthIndicator: true
        slidingWindowSize: 10 # 최근 10개의 요청을 기준으로 판단
        minimumNumberOfCalls: 5 # 최소 5번의 호출은 있어야 계산 시작
        permittedNumberOfCallsInHalfOpenState: 3 # HALF-OPEN 상태에서 허용할 요청 수
        waitDurationInOpenState: 10s # OPEN 상태에서 10초 대기 후 HALF-OPEN으로 전환
        failureRateThreshold: 50 # 실패율이 50% 넘으면 OPEN

3단계: 서비스 코드에 적용

@CircuitBreaker 애노테이션을 사용합니다.

@Service
public class OrderService {

    private final RestTemplate restTemplate;

    // 'name'은 yaml 설정의 이름과 일치해야 합니다
    @CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
    public String processOrder(Order order) {
        // 이 호출이 50% 확률로 실패하면 회로가 열립니다(Open)
        return restTemplate.getForObject("http://payment-service/pay", String.class);
    }

    // 폴백 메서드 (FALLBACK METHOD)
    // 원본 메서드와 시그니처가 같아야 하며, 마지막 파라미터로 예외(Throwable)를 받습니다
    public String fallbackPayment(Order order, Throwable t) {
        return "결제 서비스가 혼잡합니다. 잠시 후 다시 시도해주세요. (캐시된 응답 반환)";
    }
}

4. 심화 개념: "슬라이딩 윈도우 (Sliding Window)"

실패를 어떻게 카운트할까요? Resilience4j는 두 가지 타입을 사용합니다.

  1. 횟수 기반 (Count-Based - 기본값): "최근 100개의 요청을 봐라."
    • 단순하고 이해하기 쉽습니다.
  2. 시간 기반 (Time-Based): "최근 10초 동안의 모든 요청을 봐라."
    • 트래픽이 매우 많은 시스템에서 "최근 100개"가 0.001초 만에 지나가 버릴 때 유용합니다.

5. 서킷 브레이커 vs. 재시도 (Retry)

학생들이 이 둘을 자주 혼동합니다.

모범 사례 (Best Practice): 둘을 결합하세요! 3번 재시도(Retry)를 합니다. 3번 다 실패하면, 그때 서킷 브레이커 입장에서 1번의 실패로 카운트합니다.

면접용 요약 체크리스트

  1. 목적: 연쇄적인 장애(Cascading Failures)를 막고 스레드 자원을 보호한다.
  2. 라이브러리: Resilience4j (Hystrix는 이제 안 씀).
  3. 상태: Closed (정상/통과), Open (차단), Half-Open (간보기/테스트).
  4. 폴백 (Fallback): 회로가 열렸을 때 실행되는 플랜 B (캐시 반환, 기본값 반환, 또는 커스텀 에러).

references